﻿#if UNITY_EDITOR

using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace AI.Graph.Editor {


    public class CreateNodeFileManager : MonoBehaviour {

        [MenuItem ("AI System/Create/C#/Only Node/State")]
        static void CreateState () {
            CreateNode ("newState.cs.txt", "State", out string nodeName);
        }


        [MenuItem ("AI System/Create/C#/Only Node/Condition")]
        static void CreateCondition () {
            CreateNode ("newCondition.cs.txt", "Condition", out string nodeName);
        }


        [MenuItem ("AI System/Create/C#/Only Node/Sub State")]
        static void CreateSubState () {
            CreateNode ("newSubState.cs.txt", "SubState", out string nodeName);
        }


        [MenuItem ("AI System/Create/C#/Only Node/Sub Condition")]
        static void CreateSubCondition () {
            CreateNode ("newSubCondition.cs.txt", "SubCondition", out string nodeName);
        }


        [MenuItem ("AI System/Create/C#/Node and View/State")]
        static void CreateStateAndView () {
            if (CreateNode ("newState.cs.txt", "State", out string nodeName)) {
                CreateView ("newStateView.cs.txt", "StateView", nodeName);
            }
        }


        [MenuItem ("AI System/Create/C#/Node and View/Condition")]
        static void CreateConditionAndView () {
            if (CreateNode ("newCondition.cs.txt", "Condition", out string nodeName)) {
                CreateView ("newConditionView.cs.txt", "ConditionView", nodeName);
            }
        }


        [MenuItem ("AI System/Create/C#/Node and View/Sub State")]
        static void CreateSubStateAndView () {
            if (CreateNode ("newSubState.cs.txt", "SubState", out string nodeName)) {
                CreateView ("newSubStateView.cs.txt", "SubStateView", nodeName);
            }
        }


        [MenuItem ("AI System/Create/C#/Node and View/Sub Condition")]
        static void CreateSubConditionAndView () {
            if (CreateNode ("newSubCondition.cs.txt", "SubCondition", out string nodeName)) {
                CreateView ("newSubConditionView.cs.txt", "SubConditionView", nodeName);
            }
        }


        static bool CreateNode (string templateName, string nodeType, out string nodeName) {
            if (TryGetTemplate (templateName, out StringBuilder template)) {
                string assetPath = GetSelectedFilePath ($"Create {nodeType}", $"New{nodeType}", "cs");

                if (string.IsNullOrEmpty (assetPath)) {
                    nodeName = null;
                    return false;
                }

                string[] splits = assetPath.Split ('/');
                nodeName = splits[splits.Length - 1].Split ('.')[0];
                template.Replace ("#NodeName#", nodeName);
                WriteFile (assetPath, template.ToString ());

                return true;
            }

            Debug.LogError ($"Could not find {nodeType} template {templateName}");
            nodeName = null;
            return false;
        }


        static bool CreateView (string templateName, string viewType, string nodeName) {
            if (TryGetTemplate (templateName, out StringBuilder template)) {
                string assetPath = GetSelectedFilePath ($"Create {viewType} for {nodeName} select an Editor Folder", $"{nodeName}View", "cs");

                if (string.IsNullOrEmpty (assetPath)) {
                    return false;
                }

                string[] splits = assetPath.Split ('/');
                string viewName = splits[splits.Length - 1].Split ('.')[0];
                template.Replace ("#ViewName#", viewName);
                template.Replace ("#NodeName#", nodeName);
                WriteFile (assetPath, template.ToString ());

                return true;
            }

            Debug.LogError ($"Could not find {viewType} template {templateName}");

            return false;
        }


        static bool TryGetTemplate (string fileName, out StringBuilder template) {
            string path = GetFilePath ("Assets/", "*.txt", fileName);

            if (path == null) {
                template = null;
                return false;
            }

            string content = ReadFile (path);
            template = new StringBuilder (content);
            return true;
        }


        static string GetFilePath (string path, string extension, string targetFileName) {
            string[] files = Directory.GetFiles (path, extension, SearchOption.AllDirectories);

            string newFile = null;

            foreach (string file in files) {
                // Get only the Filename and see if this is the file we want
                string filename = Path.GetFileName (file);
                if (filename == targetFileName) {
                    newFile = file;
                }
            }

            return newFile;
        }


        static void WriteFile (string path, string text) {
            StreamWriter writer = new StreamWriter (path);
            writer.Write (text);
            writer.Close ();

            AssetDatabase.Refresh ();
        }


        static string ReadFile (string path) {
            StreamReader reader = new StreamReader (path);
            string template = reader.ReadToEnd ();
            reader.Close ();
            return template;
        }


        static string GetSelectedFilePath (string title, string defaultName, string extension) {
            string path = AssetDatabase.GetAssetPath (Selection.activeObject);

            if (path == "") {
                path = "Assets";
            }
            else if (Path.GetExtension (path) != "") {
                path = path.Replace (Path.GetFileName (AssetDatabase.GetAssetPath (Selection.activeObject)), "");
            }

            return EditorUtility.SaveFilePanel (title, path, defaultName, extension);
        }

    }


}
#endif